package expression;

import NextClass.NativeClass;
import NextClass.NextClassAPI;
import build.Bin.Function;
import vm.baseNativeUseFunction.NativeUseFunction;
import vm.runtime.NextVMRuntime;

import java.util.ArrayList;
import java.util.Arrays;

public class BaseExpression {
    public static Object[] Deal(String[] Input, NextVMRuntime nextVMRuntime)
    throws Exception{
        Object[] objects = new Object[Input.length];
        int j = 0;
        //System.out.println(nextVMRuntime.values);
        for (String i : Input) {
            i = i.trim();
            //System.out.println(NextVMRuntime.isRunFunction(i,nextVMRuntime)+"   "+i);
            if (StringExpression.IsNumber(i)) {
                objects[j] = Integer.parseInt(i);
                j++;
                continue;
            }
            else if (StringExpression.getValueFromNextVM(i,nextVMRuntime) != null) {
                objects[j] = StringExpression.getValueFromNextVM(i,nextVMRuntime);
                j++;
                continue;
            }
            else if (NextVMRuntime.isRunFunction(i,nextVMRuntime) != null)
            {
                NextVMRuntime fn = NextVMRuntime.isRunFunction(i,nextVMRuntime);

                String funcName = i.substring(0,i.indexOf("(")).trim();
                String Content = i.substring(i.indexOf("(")+1,i.lastIndexOf(")"));
                //String regex = ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)(?=([^\\(]*\\([^\\)]*\\))*[^\\)]*$)";
                String[] split = StringExpression.splitStringTokens(Content);

                Function.putInputFunction(funcName , fn , nextVMRuntime , split);
                fn.LastRuntime = nextVMRuntime;
                fn.IsInRootFunction = true;
                fn.AllowRun = true;
                fn.run();
                objects[j] = fn.ReturnContent;
                j++;
                continue;
            }
            else if (StringExpression.IsNumber(i)) {
                objects[j] = i;
                j++;
                continue;
            }

            if (NativeUseFunction.IsNativeUseFunctionCode(i)) {
                String funcName = i.substring(0,i.indexOf("(")).trim();
                String Content = i.substring(i.indexOf("(")+1,i.lastIndexOf(")"));
                //String regex = ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)(?=([^\\(]*\\([^\\)]*\\))*[^\\)]*$)";
                String[] split = StringExpression.splitStringTokens(Content);
                ArrayList<String> arrayList = new ArrayList<>();
                arrayList.add(funcName);
                arrayList.addAll(Arrays.asList(split));
                objects[j] = NativeUseFunction.run(arrayList.toArray(new String[0]), nextVMRuntime,i);
                j++;
                continue;
            }
            NativeClass nativeClass = NextClassAPI.IsNativeClassInvokeCode(i, nextVMRuntime);
            if (nativeClass != null) {
                String Name = i.substring(0 , i.indexOf("(")).trim();
                String Invoke = Name.substring(Name.indexOf(".")+1).trim();
                String Content = i.substring(i.indexOf("(")+1, i.lastIndexOf(")")).trim();
                //String regex = ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)(?=([^\\(]*\\([^\\)]*\\))*[^\\)]*$)";
                String[] split = StringExpression.splitStringTokens(Content);
                Object[] obj = BaseExpression.Deal(split,nextVMRuntime);

                objects[j] = ( nativeClass.run(Invoke,nextVMRuntime,obj));
                j++;
                continue;
            }
            else if (i.startsWith("[") && i.toString().endsWith("]")) {
                String[] splitContent = StringExpression.splitStringTokens(i.toString().substring(1 , i.toString().length()-1));
                Object[] objs = Deal(splitContent , nextVMRuntime);

                ArrayList<Object> arrayList = new ArrayList<>(Arrays.asList(objs));
                objects[j] = arrayList;
                j++;
                continue;
            }
            else if (i.trim().startsWith("new ")) {
                /**
                 * 创建新的对象
                 */
                // 获取对象名字
                String Type = i.trim().substring(4 , i.trim().indexOf("(")).trim();
                NextVMRuntime ClassRunTime = (NextVMRuntime) nextVMRuntime.ClassMap.get(Type);
                if (NextClassAPI.nativeClassHashMap.containsKey(Type)) {
                    String Content = i.substring(i.indexOf("(")+1,i.lastIndexOf(")")).trim();
                    //String regex = ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)(?=([^\\(]*\\([^\\)]*\\))*[^\\)]*$)";
                    String[] split = StringExpression.splitStringTokens(Content);

                    NativeClass nClass = NextClassAPI.nativeClassHashMap.get(Type);
                    Object[] inObjs = BaseExpression.Deal(split,nextVMRuntime);
                    nClass.Init(Type , inObjs);
                    objects[j] = nClass;
                }
                else {
                    NextVMRuntime fn = ClassRunTime.Functions.get("init");
                    if (fn != null) {
                        String Content = i.substring(i.indexOf("(")+1,i.lastIndexOf(")")).trim();
                        String[] split = StringExpression.splitStringTokens(Content);
                        Function.putInputFunction("init" , fn , nextVMRuntime , split);
                        fn.run();
                    }
                    objects[j] = ClassRunTime;
                }
                j++;
                continue;
            }
            else {
                try {
                    objects[j] = MathExpression.evaluateExpression(i,nextVMRuntime);
                    continue;
                }catch (Exception ignored) {
                }
                try {
                    objects[j] = StringExpression.getExpression(i,nextVMRuntime);
                }catch (Exception e) {
                    if (i.equalsIgnoreCase("true") || i.equalsIgnoreCase("false")) {
                        objects[j] = Boolean.parseBoolean(i);
                    }else {
                        objects[j] = i;
                    }
                }
                j++;
                continue;
            }
        }
        return objects;
    }
}
